package com.chengh.nami.web.controller.system;

import com.chengh.nami.common.domain.pojo.SysMenu;
import com.chengh.nami.common.domain.pojo.SysRole;
import com.chengh.nami.common.request.PageQuery;
import com.chengh.nami.common.response.PageData;
import com.chengh.nami.common.response.R;
import com.chengh.nami.system.domain.dto.RoleDto;
import com.chengh.nami.system.service.ISysMenuService;
import com.chengh.nami.system.service.ISysRoleMenuService;
import com.chengh.nami.system.service.ISysRoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author chengh
 * @Date 2023-01-02 17:32
 * @Description: 角色控制器
 */
@Tag(name = "SysRoleController", description = "角色管理")
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/system/role")
public class SysRoleController {

    private final ISysRoleService roleService;
    private final ISysMenuService menuService;
    private final ISysRoleMenuService roleMenuService;

    /**
     * 分页也获取角色信息
     *
     * @param roleDto   查询条件
     * @param pageQuery 分页条件
     * @return 角色信息
     */
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @Operation(summary = "根据条件获取角色分页信息", description = "根据条件获取角色分页信息, 需要权限'system:role:list' ")
    @GetMapping("/list")
    public R<PageData<SysRole>> list(RoleDto roleDto, PageQuery pageQuery) {
        return R.ok(roleService.getList(roleDto, pageQuery));
    }

    /**
     * 添加角色
     *
     * @param role 角色信息
     * @return 是否成功
     */
    @PreAuthorize("@ss.hasPermi('system:role:add')")
    @PostMapping
    @Operation(summary = "添加角色", description = "添加角色， 需要权限'system:role:add'")
    public R<Void> addRole(@RequestBody SysRole role) {
        return R.bool(roleService.addRole(role));
    }

    /**
     * 根据ID查询角色信息
     *
     * @param id 角色ID
     * @return 角色信息
     */
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @Operation(summary = "根据角色ID查询角色信息", description = "根据角色ID查询角色信息，需要权限‘system:role:list’")
    @GetMapping("{id}")
    public R<SysRole> getRole(@PathVariable Long id) {
        SysRole role = roleService.getById(id);
        return R.ok(role);
    }

    /**
     * 修改角色信息
     *
     * @param sysRole 角色信息
     * @return 是否成功
     */
    @PreAuthorize("@ss.hasAnyPermi('system:role:edit')")
    @PutMapping
    @Operation(summary = "修改角色", description = "修改角色，需要权限system:role:edit")
    public R<Void> update(@RequestBody SysRole sysRole) {
        return R.bool(roleService.editRole(sysRole));
    }

    /**
     * 根据角色ID集合删除角色信息
     *
     * @param ids 角色集合ID
     * @return 是否成功
     */
    @PreAuthorize("@ss.hasAnyPermi('system:role:del')")
    @DeleteMapping("/{ids}")
    @Operation(summary = "删除角色", description = "修改角色，需要权限system:role:del")
    public R<Void> delete(@PathVariable List<Long> ids) {
        return R.bool(roleService.delRole(ids));
    }

    /**
     * 查询全部䣌菜单以及已分配的菜单
     */
    @GetMapping("/treeMenus/{roleId}")
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @Operation(summary = "查询全部䣌菜单以及已分配的菜单", description = "查询全部䣌菜单以及已分配的菜单, 需要权限system:role:list")
    public R<Map<String, Object>> treeMenus(@PathVariable Long roleId) {
        // 获取角色已经拥有的权限
        List<SysMenu> menus = menuService.getMenuByRoleId(roleId);
        List<Long> menuIds = menus.stream().map(SysMenu::getId).collect(Collectors.toList());
        // 获取所有的菜单权限
        List<SysMenu> list = getTreeMenus(menuService.list());
        HashMap<String, Object> stringObjectHashMap = new HashMap<>(2);
        stringObjectHashMap.put("menus", list);
        stringObjectHashMap.put("ids", menuIds);
        return R.ok(stringObjectHashMap);
    }

    @PostMapping("/updateRoleMenus")
    @PreAuthorize("@ss.hasPermi('system:role:menu')")
    @Operation(summary = "分配角色的权限", description = "分配角色的权限, 需要权限system:role:menu")
    public R<Void> updateRoleMenus(@RequestBody RoleDto roleDto) {
        boolean b = roleMenuService.updateRoleMenus(roleDto.getId(), roleDto.getMenuIds());
        return R.bool(b);
    }

    private List<SysMenu> getTreeMenus(List<SysMenu> menus) {
        return menus.stream().filter(menu -> menu.getParentId() == 0).
                peek((menu) -> menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
    }

    /**
     * 递归获取子菜单
     *
     * @param menu  菜单列表
     * @param menus 最上级菜单
     * @return 菜单树
     */
    private List<SysMenu> getChildren(SysMenu menu, List<SysMenu> menus) {
        return menus.stream().filter(
                item -> item.getParentId().equals(menu.getId())
        ).peek(item -> item.setChildren(getChildren(item, menus))).collect(Collectors.toList());
    }

    @PostMapping("/export")
    public void exportExcel(HttpServletResponse response, RoleDto roleDto, PageQuery pageQuery) {
        roleService.exportRoleExcle(response, roleDto, pageQuery);
    }
}
